<?php
// $Id: View.php 27 2010-11-16 12:49:54Z mjohnson60@gmail.com $


/**
 * Enter description here ...
 * 
 * @author Mark Phillip Johnson
 * @version 1.0
 * @copyright Copyright (c) 2010, markjohnson
 * @license http://www.gnu.org/licenses/gpl.html The GNU General Public License v3.0
 *
 */
class View extends Object
{
	/**
	 * @var string The model type (ie. page, links, etc.)
	 */
	protected $model = '';
	
	/**
	 * @var string The title of the view 
	 */
	protected $title = '';
	
	/**
	 * @var float The view's opacity. This value will be used in CSS.
	 */
	protected $alpha = 1.0;
	
	/**
	 * @var bool Whether the view is hidden or not. This value will also be used in CSS.
	 */
	protected $hidden = FALSE;
	
	/**
	 * @var array General CSS styling rules.
	 */
	protected $style = array();
	
	/**
	 * @var array
	 */
	protected $subviews = array();
	
	/**
	 * @var array
	 */
	protected $keyedSubviews = array();
	
	/**
	 * @var View
	 */
	protected $superview = NULL;
	
	/**
	 * @var int
	 */
	protected $tag = 0;
	
	/**
	 * @var string
	 */
	protected $template = FALSE;
	
	/**
	 * @var string Enter description here ...
	 */
	protected $templateFile = NULL;
	
	/**
	 * @var string Enter description here ...
	 */
	protected $templatePath = NULL;
	
	/**
	 * @var unknown_type Enter description here ...
	 */
	protected $prefix = '';
	
	/**
	 * @var unknown_type Enter description here ...
	 */
	protected $suffix = '';
	
	/**
	 * @var boolean Enter description here ...
	 */
	protected $rendered = FALSE;
	
	/**
	 * @var string
	 */
	protected $content = '';

	/**
	 * 
	 */
	public function __construct()
	{
		parent::__construct();
	
		//TODO - Insert your code here
	}

	/**
	 * @return the $model
	 */
	public function model()
	{
		return $this->model;
	}

	/**
	 * @param string $model
	 */
	public function setModel($model)
	{
		$this->model = $model;
	}

	/**
	 * @return the $title
	 */
	public function title()
	{
		return $this->title;
	}

	/**
	 * @param string $title
	 */
	public function setTitle($title)
	{
		$this->title = $title;
	}

	/**
	 * @return the $alpha
	 */
	public function alpha()
	{
		return $this->alpha;
	}

	/**
	 * @param float $alpha
	 */
	public function setAlpha($alpha)
	{
		$this->alpha = $alpha;
	}

	/**
	 * @return the $hidden
	 */
	public function hidden()
	{
		return $this->hidden;
	}

	/**
	 * @param bool $hidden
	 */
	public function setHidden($hidden)
	{
		$this->hidden = $hidden;
	}

	/**
	 * @return the $styles
	 */
	public function style()
	{
		return $this->style;
	}

	/**
	 * @param array $styles
	 */
	public function addStyle($style)
	{
		$this->style[] = $style;
	}

	/**
	 * @return the $subviews
	 */
	public function subviews()
	{
		return $this->subviews;
	}

	/**
	 * @param array $subviews
	 */
	public function setSubviews($subviews)
	{
		$this->subviews = $subviews;
	}

	/**
	 * @return the $keyedSubviews
	 */
	public function keyedSubviews()
	{
		return $this->keyedSubviews;
	}

	/**
	 * @param array $keyedSubviews
	 */
	public function setKeyedSubviews($keyedSubviews)
	{
		$this->keyedSubviews = $keyedSubviews;
	}

	/**
	 * @return the $tag
	 */
	public function tag()
	{
		return $this->tag;
	}

	/**
	 * @param int $tag
	 */
	public function setTag($tag)
	{
		$this->tag = $tag;
	}

	/**
	 * @return the $prefix
	 */
	public function prefix()
	{
		return $this->prefix;
	}

	/**
	 * @param unknown_type $prefix
	 */
	public function setPrefix($prefix)
	{
		$this->prefix = $prefix;
	}

	/**
	 * @return the $suffix
	 */
	public function suffix()
	{
		return $this->suffix;
	}

	/**
	 * @param unknown_type $suffix
	 */
	public function setSuffix($suffix)
	{
		$this->suffix = $suffix;
	}

	/**
	 * @return the $rendered
	 */
	public function rendered()
	{
		return $this->rendered;
	}

	/**
	 * @param boolean $rendered
	 */
	public function setRendered($rendered)
	{
		$this->rendered = $rendered;
	}

	/**
	 * @return the $content
	 */
	public function content()
	{
		return $this->content;
	}

	/**
	 * @param string $content
	 */
	public function setContent($content)
	{
		$this->content = $content;
	}

	/**
	 * Enter description here ...
	 * 
	 * @return string|boolean
	 */
	public function template()
	{
		if (!empty($this->template))
		{
			return dirname(__FILE__) . '/' . $this->template;
		}
		else
		{
			return FALSE;
		}
	}

	/**
	 * @param string $template
	 */
	public function setTemplate($template)
	{
		$this->template = $template;
	}

	/**
	 * Enter description here ...
	 * 
	 */
	public function templateFile()
	{
		return $this->templateFile;
	}

	/**
	 * Enter description here ...
	 * 
	 * @param string $templatePath
	 */
	public function setTemplateFile($templateFile)
	{
		$this->templateFile = $templateFile;
	}

	/**
	 * Enter description here ...
	 * 
	 */
	public function templatePath()
	{
		return $this->templatePath;
	}

	/**
	 * Enter description here ...
	 * 
	 * @param string $templatePath
	 */
	public function setTemplatePath($templatePath)
	{
		$this->templatePath = $templatePath;
	}

	/**
	 * @return the $superview
	 */
	public function superview()
	{
		return $this->superview;
	}

	/**
	 * @param View $superview
	 */
	public function setSuperview(View $superview)
	{
		if ($superview instanceof View)
		{
			$this->superview = $superview;
		}
	}

	/**
	 * Enter description here ...
	 * 
	 * @param array $variables
	 * @return string
	 */
	public function render($variables = array())
	{
		$output = '';
		
		$this->rendered = TRUE;
		
		foreach ($this->subviews as $subview)
		{
			$output .= $subview->render($variables);
		}
		
		$this->content = $output;
		
		$output = $this->draw($output);
		
		return $this->prefix . $output . $this->suffix;
	}

	/**
	 * Enter description here ...
	 * 
	 * @return string Returns the rendered view. 
	 */
	public function draw(string $content)
	{
		return '<div class="view">' . "\n" . $content . "\n" . '</div>' . "\n";
	}

	/**
	 * Enter description here ...
	 * 
	 */
	public final function reindexSubviews()
	{
		$this->subviews = array_values($this->subviews);
	}

	/**
	 * Enter description here ...
	 * 
	 * @param View $subview
	 * @param string $key
	 */
	public function addSubview(View &$subview, string $key)
	{
		if ($subview instanceof View)
		{
			$this->subviews[] = $subview;
			$this->keyedSubviews[$key] = $subview;
			
			$subview->setSuperview($this);
			
			$this->didAddSubview($subview);
		}
	}

	/**
	 * Enter description here ...
	 * 
	 * @param View $subview
	 */
	public function bringSubviewToFront(View &$subview)
	{
		$index = array_search($subview, $this->subviews);
		if ($index !== FALSE)
		{
			unset($this->subviews[$index]);
			$this->subviews[] = $subview;
			
			$this->reindexSubviews();
		}
	}

	/**
	 * Enter description here ...
	 * 
	 * @param View $subview
	 */
	public function didAddSubview(View &$subview)
	{
	
	}

	/**
	 * Enter description here ...
	 * 
	 * @param View $subview
	 * @param string $key
	 * @param View $siblingView
	 */
	public function insertSubviewAboveSubview(View &$subview, string $key, View $siblingView)
	{
		$index = array_search($siblingView, $this->subviews);
		$this->insertSubviewAtIndex($subview, $key, $index);
	}

	/**
	 * Enter description here ...
	 * 
	 * @param View $subview
	 * @param string $key
	 * @param View $siblingView
	 */
	public function insertSubviewBelowSubview(View &$subview, string $key, View $siblingView)
	{
		$index = array_search($siblingView, $this->subviews);
		$this->insertSubviewAtIndex($subview, $key, $index - 1);
	}

	/**
	 * Enter description here ...
	 * 
	 * @param View $subview
	 * @param string $key
	 * @param int $index
	 */
	public function insertSubviewAtIndex(View &$subview, string $key, int $index)
	{
		if (!empty($index) && !empty($subview) && $subview instanceof View)
		{
			$start = array_slice($this->subviews, 0, $index);
			$end = array_slice($this->subviews, $index + 1);
			$start[] = $subview;
			
			$this->subviews = array_merge($start, $end);
			$this->keyedSubviews[$key] = $subview;
			
			$this->reindexSubviews();
			$subview->setSuperview($this);
			
			$this->didAddSubview($subview);
		}
	}

	/**
	 * Enter description here ...
	 * 
	 * @param View $subview
	 */
	public function sendSubviewToBack(View &$subview)
	{
		$index = array_search($subview, $this->subviews);
		if ($index !== FALSE)
		{
			unset($this->subviews[$index]);
			array_unshift($this->subviews, $subview);
			
			$this->reindexSubviews();
		}
	}

	/**
	 * Enter description here ...
	 * 
	 * @param View $view
	 * @return boolean
	 */
	public function isDescendantOfView(View $view)
	{
		if (!empty($this->superview))
		{
			if ($this->superview === $view)
			{
				return TRUE;
			}
			else
			{
				return $this->superview->isDescendantOfView($view);
			}
		}
		else
		{
			return FALSE;
		}
	}

	/**
	 * Enter description here ...
	 * 
	 * @param View $subview
	 */
	public function removeSubview(View $subview)
	{
		$index = array_search($subview, $this->subviews);
		$key = array_search($subview, $this->keyedSubviews);
		if ($index !== FALSE && $key !== FALSE)
		{
			$this->willRemoveSubview($subview);
			
			unset($this->subviews[$index]);
			unset($this->keyedSubviews[$key]);
			
			$this->reindexSubviews();
		}
	}

	/**
	 * Enter description here ...
	 * 
	 */
	public function removeFromSuperview()
	{
		if (!empty($this->superview))
		{
			$this->superview->removeSubview($this);
		}
	}

	/**
	 * Enter description here ...
	 * 
	 * @param View $subview
	 */
	public function willRemoveSubview(View &$subview)
	{
	
	}
}
